home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
TPUG - Toronto PET Users Group
/
TPUG Users Group CD
/
TPUG Users Group CD.iso
/
AMIGA
/
AMICUS
/
AMICUS26.ADF
/
SoundScape
/
LatticeExamples
/
movie.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-01-26
|
13KB
|
379 lines
/* MOVIE.C Animation Queue Sheet generator
(c) 1986 Todor Fay
This program takes a composed track and computes a score chart
for the first 16 tracks, with events marked every frame.
Link this with lib/sslink.obj.
*/
#include "exec/types.h"
#include "exec/exec.h"
#include "libraries/dos.h"
#include "intuition/intuition.h"
#include "soundscape.h"
#include "modules/tapedeck.h"
/* This program installs itself in the SoundScape environment,
so it needs to have an icon. The following data describes
an image of a short piece of film:
*/
UWORD filmdata[] = { /* 36 x 17 */
0, 0, 0,
14844, 15985, 49152,
392, 7800, 0,
377, 15960, 0,
14655, 65273, 49152,
303, 65272, 0,
0, 0, 0,
14844, 15993, 49152,
392, 7792, 0,
377, 15992, 0,
14655, 65241, 49152,
303, 65272, 0,
0, 0, 0,
14844, 15993, 49152,
392, 7800, 0,
377, 15984, 0,
14655, 65273, 49152,
65535, 65535, 61440,
50688, 646, 12288,
65136, 663, 61440,
65167, 62119, 61440,
50703, 45574, 12288,
65031, 49671, 63488,
65535, 65535, 64512,
50688, 646, 15360,
65136, 647, 64512,
65167, 62103, 64512,
50703, 12838, 14336,
65031, 49671, 61440,
65535, 65535, 61440,
50688, 646, 12288,
65136, 647, 61440,
65167, 62087, 61440,
50703, 29206, 12288,
};
struct Image filmimage =
{ 0,0,36,17,2,&filmdata[0],3,0,0, };
struct IntuiText filmtext[] = {
{ 2,0,JAM2,-32,0,0,"CPS",0 },
{ 2,0,JAM2,-48,0,0,"Start",0 },
{ 2,0,JAM2,-48,0,0,"Count",0 },
{ 3,0,JAM2,0,20,0,"Do it",0 },
};
struct StringInfo filminfo[] = {
{ "60\0 ",0,0,6,0,0,0,0,0,0,0,0,0, },
{ "0\0 ",0,0,6,0,0,0,0,0,0,0,0,0, },
{ "1\0 ",0,0,6,0,0,0,0,0,0,0,0,0, },
};
short box[] = { 0,0,52,0,52,10,0,10,0,0 };
struct Border gadgetborder = { -2,-2,3,0,JAM2,5,&box[0],0 };
struct Gadget filmgadgets[] = {
{ 0,60,15,48,8,
GADGHCOMP,GADGIMMEDIATE | RELVERIFY | LONGINT, STRGADGET,
&gadgetborder,0,&filmtext[0],0,&filminfo[0],0,0, },
{ &filmgadgets[0],60,25,48,8,
GADGHCOMP,GADGIMMEDIATE | RELVERIFY | LONGINT, STRGADGET,
&gadgetborder,0,&filmtext[1],0,&filminfo[1],1,0, },
{ &filmgadgets[1],60,35,48,8,
GADGHCOMP,GADGIMMEDIATE | RELVERIFY | LONGINT, STRGADGET,
&gadgetborder,0,&filmtext[2],0,&filminfo[2],2,0, },
{ &filmgadgets[2],120,15,36,30,
GADGHCOMP | GADGIMAGE,GADGIMMEDIATE | RELVERIFY, BOOLGADGET,
&filmimage,0,&filmtext[3],0,0,3,0, },
};
struct NewWindow filmwindow = {
0,0,190,50,2,1,GADGETUP | CLOSEWINDOW,
WINDOWCLOSE | WINDOWDRAG | ACTIVATE | WINDOWDEPTH | SMART_REFRESH | WINDOWSIZING,
&filmgadgets[3],0," Film Score ",0,0,40,20,0,0,WBENCHSCREEN
};
static char outbuff[100];
char printit = 0;
linedone()
/* When a line is ready to print, run through it and strip out all
the nulls that were generated by the integer to character conversions.
Then, put a null back after the last number, so only this much of the
line will be printed.
*/
{
short i;
short last = 0;
for (i=0; i<80; i++) {
if (!outbuff[i]) {
outbuff[i] = ' ';
last = i;
}
}
outbuff[last] = 0;
}
newline(time)
/* Prepare the buffer for a new line by clearing it and putting
the time in seconds and frames at the start of it.
'stcu_d' is the Lattice decimal integer to ascii routine.
*/
long time;
{
short i;
setmem(outbuff,80,' ');
stcu_d(outbuff,(time / 24),10);
i = strlen(outbuff);
outbuff[i] = ':';
stcu_d(&outbuff[i + 2],(time % 24),10);
}
outcode(note)
/* This routine is called by SoundScape whenver there is a note for
this device.
We want to take the note and stick its value in outbuff, positioned
by the MIDI channel.
If note off event (the velocity is 0), ignore it.
*/
struct Note *note;
{
short channel = note->status & 0x0F;
unsigned char stat = note->status & 0xF0;
if (note->velocity) {
stcu_d(&outbuff[(channel * 4) + 10],note->value,4);
}
FreeNode(note); /* Return the note to SoundScape. */
}
opencode(direction)
/* You must provide code for SoundScape to open your port (AddMidiPort
installs it, but doesn`t activate it.)
Each port handles both input and output, or one or the other.
Direction says which one to open.
In this case, we don't have anything to do, just return TRUE.
An example where opencode would do something would be if your
output port involved a display window. Opencode(0) would instruct
you to open that window. Closecode(0) would instruct you to close
it.
*/
char direction;
{
return(1);
}
closecode(direction)
char direction;
{
return(1);
}
editcode(direction,command,buffer)
/* We aren't providing any of the edit options. However, should somebody
wish to edit the state, let them know the size is 0.
*/
char direction, command;
long buffer[];
{
buffer[0] = 0;
return(0);
}
long SoundScapeBase, IntuitionBase;
main() {
long time = 0;
short linecount = 0;
long frames = 0;
long oldframes = 0;
long startpoint = 0;
long stoppoint = 24;
long framesleft;
long clockspersecond = 60;
short page;
long file;
char filename[40];
char pagestring[10];
struct Window *window;
static char tracktop[] = "\n\nTime <----------------------- Tracks ----------------------------->\n";
static char pagetop[] = "Sec:Frame 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16\n\n";
static char tabs[] = "\t\t\t\t page ";
char carriagereturn = '\n';
char formfeed = 12;
struct IntuiMessage *message;
struct Note *note;
struct Track *track;
struct TapeState ts;
short i;
short thisport;
struct Gadget *gadget;
IntuitionBase = OpenLibrary("intuition.library",0);
SoundScapeBase = OpenLibrary("soundscape.library",0);
if (!SoundScapeBase) {
CloseLibrary(IntuitionBase);
return;
}
window = OpenWindow(&filmwindow);
if (!window) {
CloseLibrary(IntuitionBase);
CloseLibrary(SoundScapeBase);
return;
}
/* Add this port to the system. We specify a desired port id of -1,
in other words any port. */
thisport = AddMidiPort(opencode,closecode,editcode,outcode,
&filmimage,&filmimage,-1,"Animator's Helper");
/* Open this port. Though our opencode does nothing, SoundScape will. */
OpenMidiPort(thisport,0);
OpenMidiPort(thisport,1);
/* Open the tape deck. */
OpenMidiPort(6,0);
filename[0] = 0;
for(;;) {
while (message = (struct IntuiMessage *) GetMsg(window->UserPort))
ReplyMsg(message);
while (!(message = (struct IntuiMessage *) GetMsg(window->UserPort)))
WaitPort(window->UserPort);
if (message->Class == CLOSEWINDOW) break;
gadget = message->IAddress;
ReplyMsg(message);
switch (gadget->GadgetID) {
case 0 :
clockspersecond = filminfo[0].LongInt;
break;
case 1 :
startpoint = (filminfo[1].LongInt * 24);
break;
case 2 :
stoppoint = (filminfo[2].LongInt * 24);
break;
case 3 : /* Do it. */
time = (startpoint * clockspersecond) / 24;
/* Get the tape deck state. */
EditMidiPort(6,0,2,&ts);
/* Release the tracks. */
FreeTree(ts.toptrack);
/* Set them to 0. */
ts.toptrack = ts.activetrack = 0;
ts.trackname[0] = 0;
EditMidiPort(6,0,3,&ts);
/* Read in a new set of tracks (the song). */
ts.toptrack = ts.activetrack = ReadList(TRACK,ts.trackname);
/* Give the tape deck this song and set the timer and punch points. */
ts.td_timer = time;
ts.punchin = ts.punchout = 0;
EditMidiPort(6,0,3,&ts);
/* If there was no song, leave. */
if (!ts.toptrack) break;
/* Get the name of the file to save to. Template is .film */
WriteFileName(filename,"Film File","film");
/* If the user selected QUIT, filename[0] is 0. */
if (!filename[0]) break;
file = Open(filename,MODE_NEWFILE);
if (!file) break;
/* Put in the top of page information. */
Write(file,ts.trackname,strlen(ts.trackname));
Write(file,tabs,strlen(tabs));
page = 1;
stcu_d(pagestring,page,10);
Write(file,pagestring,strlen(pagestring));
Write(file,tracktop,strlen(tracktop));
Write(file,pagetop,strlen(pagetop));
i = 0;
/* Set the first 16 tracks to send to this port and each one has
its own MIDI channel. */
for (track = ts.toptrack; i < 16; i++ ) {
if (!track) break;
track->channelout = i;
track->portout = thisport;
track = track->link.next;
}
/* Make sure the tape deck is STOPPED (or it won't START.) */
note = AllocNode(NOTE);
note->status = STOP;
OutMidiPort(6,note);
/* Fast forward the tapedeck to where we want to start. */
note = AllocNode(NOTE);
note->status = SONGPOSITION;
/* MIDI Song position is clocks divided by 6. */
i = time / 6;
note->value = i & 0x7F;
note->velocity = (i >> 7) & 0x7F;
/* But internally, SoundScape lets you include the mod 6. */
note->duration = time % 6;
OutMidiPort(6,note);
/* Tell the tapedeck to start playing from this point. */
note = AllocNode(NOTE);
note->status = CONTINUE;
OutMidiPort(6,note);
frames = startpoint;
framesleft = stoppoint;
oldframes = frames;
newline(frames);
linecount = 0;
while (framesleft) {
oldframes = frames;
frames = (time * 24) / clockspersecond;
/* Send a clock pulse. As soon as it goes out, the tape deck, which runs
at a higher priority, will call outcode for each of the notes it is
ready to send at this point in time. */
note = AllocNode(NOTE);
note->status = CLOCK;
OutMidiPort(6,note);
/* All events for this MIDI click should be in outbuff now.
See if we've done enough to move to a new frame. */
if (frames != oldframes) {
/* New frame. Print this one, then prepare for the next. */
framesleft--;
linedone();
Write(file,outbuff,strlen(outbuff));
Write(file,&carriagereturn,1);
if (++linecount == 48) {
if (!framesleft) break;
page++;
linecount = 0;
Write(file,&formfeed,1);
Write(file,ts.trackname,strlen(ts.trackname));
Write(file,tabs,strlen(tabs));
stcu_d(pagestring,page,10);
Write(file,pagestring,strlen(pagestring));
Write(file,tracktop,strlen(tracktop));
Write(file,pagetop,strlen(pagetop));
}
/* Delay so the low priority task that prints the tape deck counter
has a chance to do so. */
Delay(2);
newline(frames);
}
time++;
}
Close(file);
break;
}
}
CloseWindow(window);
RemoveMidiPort(thisport);
CloseLibrary(SoundScapeBase);
CloseLibrary(IntuitionBase);
}